<template>
  <el-dialog v-model="showDialog" :before-close="handleClose">
    <template #header>
      <span style="font-size: 20px; font-weight: 800">{{
        isLogin ? "登录" : "注册"
      }}</span>
    </template>
    <div class="login-main">
      <div class="login-have-account">
        <div v-if="isLogin" class="no-account">
          没有账号？<span class="line" @click="toRegister">去注册</span>
        </div>
        <div v-else class="no-account">
          已有账号？<span class="line" @click="toLogin">去登录</span>
        </div>
      </div>
      <el-form
        v-if="isLogin"
        class="login-register-form"
        ref="loginFormRef"
        :model="loginForm"
        :rules="loginRules"
      >
        <div class="login-blank">
          <el-image
            style="width: 80px; height: 80px"
            :src="blogAvatar"
            fit="cover"
          />
        </div>
        <el-form-item prop="username">
          <el-input
            v-model="loginForm.username"
            :style="{ width: '100%' }"
            placeholder="请输入用户名"
            clearable
            @keyup.enter="submit"
          />
        </el-form-item>
        <el-form-item prop="password" @keyup.enter="submit">
          <el-input
            v-model="loginForm.password"
            show-password
            :style="{ width: '100%' }"
            placeholder="请输入密码"
            clearable
          />
        </el-form-item>
      </el-form>
      <el-form
        v-else
        class="login-register-form"
        ref="registerFormRef"
        :model="registerForm"
        :rules="registerRules"
      >
        <el-form-item prop="username">
          <el-input
            v-model="registerForm.username"
            :style="{ width: '100%' }"
            placeholder="请输入用户名"
            clearable
          />
        </el-form-item>
        <el-form-item>
          <el-input
            v-model="registerForm.nickName"
            :style="{ width: '100%' }"
            placeholder="请输入昵称"
            clearable
          />
        </el-form-item>
        <el-form-item prop="email">
          <el-input
            v-model="registerForm.email"
            :style="{ width: '100%' }"
            placeholder="邮箱"
            clearable
          />
        </el-form-item>
        <el-form-item prop="captcha">
          <el-input
            v-model="registerForm.captcha"
            :style="{ width: '60%' }"
            placeholder="邮箱验证码"
            clearable
            @keyup.enter="submit"
          />
          <el-button
            :style="{ margin: '4px' }"
            type="primary"
            :disabled="disabledCaptcha"
            @click="getEmailCaptcha()"
            >{{ captchaTimer }}</el-button
          >
        </el-form-item>
        <el-form-item prop="password1">
          <el-input
            show-password
            v-model="registerForm.password1"
            :style="{ width: '100%' }"
            placeholder="请输入密码"
            clearable
          />
        </el-form-item>
        <el-form-item prop="password2">
          <el-input
            show-password
            v-model="registerForm.password2"
            :style="{ width: '100%' }"
            placeholder="确认密码"
            clearable
            @keyup.enter="submit"
          />
        </el-form-item>
      </el-form>
      <div v-if="isLogin" class="login-register-button flex-sty">
        <span class="apply-button" @click="submit">登录</span>
      </div>
      <div v-else class="login-register-button flex-sty">
        <span class="apply-button" @click="submit">注册</span>
      </div>
    </div>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, watch, h, nextTick, onMounted, computed } from "vue";

import { login, registerUser, getCaptcha } from "@/api/login";

import { user } from "@/store";
import { setCookie } from "@/utils/token";
import { _setLocalItem, _getLocalItem, _removeLocalItem } from "@/utils/tools";
// 加密解密
import aes from "@/utils/aes";

import { ElNotification } from "element-plus";
import { storeToRefs } from "pinia";
// import { useRouter } from "vue-router";
const userStore = user();
// const router = useRouter();
const { getShowLogin } = storeToRefs(userStore);

const blogAvatar = new URL("../../assets/j-logo.webp", import.meta.url)
  .href
// 获取验证码按钮是否禁用
const disabledCaptcha = ref(false);

// 验证码倒计时
const captchaTimer = ref("获取邮箱验证码");

const usernameValid = (rule: any, value: string, cb: Function) => {
  if (!value) {
    return cb(new Error("请输入用户账号"));
  } else if (value.length > 16 || value.length < 5) {
    return cb(new Error("用户账号长度应该在5-16之间"));
  }
  cb();
};
const REGEXP_EMAIL = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
const emailvalid = (rule: any, value: string, cb: Function) => {
  if (!value) {
    return cb(new Error("请输入密码"));
  } else if (!REGEXP_EMAIL.test(value)) {
    return cb(new Error("密码格式应为8-18位数字、字母、符号的任意两种组合"));
  }
  cb();
};
const REGEXP_PWD =
  /^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)]|[()])+$)(?!^.*[\u4E00-\u9FA5].*$)([^(0-9a-zA-Z)]|[()]|[a-z]|[A-Z]|[0-9]){6,18}$/;
const password1Valid = (rule: any, value: string, cb: Function) => {
  if (!value) {
    return cb(new Error("请输入密码"));
  } else if (!REGEXP_PWD.test(value)) {
    return cb(new Error("密码格式应为8-18位数字、字母、符号的任意两种组合"));
  }
  cb();
};

const password2Valid = (rule: any, value: string, cb: Function) => {
  if (!value) {
    return cb(new Error("请输入二次确认密码"));
  } else if (value != registerForm.password1) {
    return cb(new Error("两次密码不一致"));
  }
  cb();
};

const loginFormRef = ref();
interface Register {
  username: string;
  password: string;
  nickName: string;
  email: string;
  captcha: string;
  headPic: string;
}

type Login = Pick<Register, "username" | "password">;
const loginForm = reactive<Login>({
  username: "",
  password: "",
});
const primaryLoginForm = reactive({ ...loginForm });

const registerFormRef = ref();
const registerForm = reactive({
  username: "", // 用户名
  email: "",
  captcha: "",
  password1: "", // 密码
  password2: "", // 确认密码
  nickName: "", // 昵称
  headPic: "", // 头像
});
const primaryRegisterForm = reactive({ ...registerForm });
const isLogin = ref(true);
const showDialog = ref(false);

const loginRules = {
  username: [{ required: true, message: "请输入用户账号", trigger: "blur" }],
  password: [{ required: true, message: "请输入用户密码", trigger: "blur" }],
};
const registerRules = {
  username: [{ required: true, validator: usernameValid, trigger: "blur" }],
  email: [{ required: true, validator: emailvalid, trigger: "blur" }],
  password1: [{ required: true, validator: password1Valid, trigger: "blur" }],
  password2: [{ required: true, validator: password2Valid, trigger: "blur" }],
  captcha: [{ required: true, trigger: "blur" }],
};

// 倒计时
const setTimer = () => {
  let holdTime = 30; //定义变量并赋值
  captchaTimer.value = "重新获取(30)";
  //setInterval（）是一个实现定时调用的函数，可按照指定的周期（以毫秒计）来调用函数或计算表达式。
  //setInterval方法会不停地调用函数，直到 clearInterval被调用或窗口被关闭。
  let Timer = setInterval(() => {
    if (holdTime <= -1) {
      clearInterval(Timer); //清除该函数
      captchaTimer.value = "获取邮箱验证码";
      disabledCaptcha.value = false;
      return; //返回前面
    }
    captchaTimer.value = "重新获取(" + holdTime + ")";
    holdTime--;
  }, 1000);
};
// 发送邮箱验证码
const getEmailCaptcha = () => {
  if (!registerForm.email) return;
  getCaptcha(registerForm.email)
    .then((res: any) => {
      if (res?.status === 200) {
        disabledCaptcha.value = true;
        setTimer();
        ElNotification.success({
          title: "Success",
          message: res.data,
          offset: 100,
        });
      }
    })
    .catch((err: any) => {
      ElNotification.error({
        title: "Failed",
        message: err.message,
        offset: 100,
      });
    });
};
// 用户注册
const userRegister = async () => {
  await registerFormRef.value.validate(async (valid: any) => {
    if (valid) {
      const register = {
        username: registerForm.username,
        password: registerForm.password1,
        nickName: registerForm.nickName,
        captcha: registerForm.captcha,
        email: registerForm.email,
        headPic:
          registerForm.headPic ||
          "https://jiangeges.oss-cn-heyuan.aliyuncs.com/front-end/avatar_girl.svg",
      };
      const res = await registerUser(register);
      if (res?.status == 201) {
        // 自动登录
        loginForm.username = register.username;
        loginForm.password = register.password;
        await onLogin();
      } else {
        ElNotification.error({
          offset: 60,
          title: "Failed",
          message: "注册失败",
        });
      }
    }
  });
};

// 校验
const userLogin = async () => {
  await loginFormRef.value.validate(async (valid: any) => {
    if (valid) {
      onLogin();
    }
  });
};

// 登录
const onLogin = async () => {
  try {
    const res = await login(loginForm);
    if (res.status === 201) {
      // 保存 token
      await userStore.setToken(res?.data?.accessToken || "");
      setCookie("accessToken", res?.data?.accessToken || "", { expires: 1 });
      _setLocalItem("access_token", aes.aesEncrypt(res?.data?.accessToken) || "");
      _setLocalItem("refresh_token", aes.aesEncrypt(res?.data?.refreshToken) || "");
      _setLocalItem("loginForm", aes.aesEncrypt(loginForm));
      const userinfo = res?.data?.userInfo || {};
      await userStore.setUserInfo(userinfo);
      await userStore.setHeadPic(userinfo.headPic);
      Object.assign(loginForm, primaryLoginForm);
      Object.assign(registerForm, primaryRegisterForm);
      handleClose();
      location.reload();
      ElNotification.success({
        title: "Success",
        message: "登录成功",
        offset: 100,
      });
    } else {
      ElNotification.error({
        title: "Failed",
        message: "登录失败",
        offset: 100,
      });
    }
  } catch (error:any) {
    ElNotification.error({
      title: "Failed",
      message: error.response.data.message,
      offset: 100,
    });
  }
};

const toLogin = () => {
  isLogin.value = true;
};
const toRegister = () => {
  isLogin.value = false;
};

// 提交
const submit = async () => {
  if (isLogin.value) {
    userLogin();
  } else {
    userRegister();
  }
};

const handleClose = () => {
  userStore.setShowLogin(false);
};

watch(
  () => isLogin.value,
  (newV) => {
    if (newV) {
      loginFormRef.value && loginFormRef.value.resetFields();
    } else {
      registerFormRef.value && registerFormRef.value.resetFields();
    }
  },
  {
    immediate: true,
  }
);

watch(
  () => getShowLogin.value,
  (newV) => {
    showDialog.value = newV;
    if (newV) {
      isLogin.value = true;
      nextTick(() => {
        loginFormRef.value && loginFormRef.value.resetFields();
        registerFormRef.value && registerFormRef.value.resetFields();

        // 判断用户是否被记住了
        let form = aes.aesDecrypt(_getLocalItem("loginForm"));
        if (form) {
          Object.assign(loginForm, JSON.parse(form));
        }
      });
    }
  },
  {
    immediate: true,
  }
);
</script>
<style lang="scss" scoped>
.el-dialog {
  --el-dialog-width: 100% !important;
  width: var(--el-dialog-width, 100%) !important;
}
.login-main {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  .login-have-account {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
  }
}
.login-blank {
  width: 100%;
  height: 10rem;
}
.login-register {
  &-form {
    width: 100%;
  }
}
.apply-button {
  width: 100%;
  text-align: center;
  cursor: pointer;
}
.line {
  cursor: pointer;
  text-decoration: underline;
}
.no-account {
  font-size: 1rem;
}

:deep(.el-form-item) {
  padding: 15px 0;
}

:deep(.el-input__wrapper) {
  height: 40px;
  line-height: 40px;
}

.remember-me {
  padding: 0;
}

.flex-sty {
  @include flex();
  width: 100%;
}

.login-register-button {
  height: 40px;
  font-size: 18px;
  font-weight: bold;
  background: linear-gradient(to right, #5fdaff, #7b84fe);
  border-radius: 5px;
  margin-bottom: 30px;
}

// pc
@media screen and (min-width: 768px) {
  .login-box {
    height: 50vh !important;
  }
}

// mobile
@media screen and (max-width: 768px) {
  .login-register-box {
    width: 80%;
  }

  .login-box {
    height: 88vh !important;
  }
}
</style>
